﻿using System;
using UnityEngine;
using UnityEngine.UIElements;

namespace winS.UnityEditor.UIElement
{
    /// <summary>
    /// 最小最大滑动条
    /// </summary>
    public class MinMaxSlider : EditorField<Vector2>
    {
        public static readonly float valueFieldWidth = 40f;

        public float minLimit { get => minMaxSlider.lowLimit; set => minMaxSlider.lowLimit = value; }
        public float maxLimit { get => minMaxSlider.highLimit; set => minMaxSlider.highLimit = value; }

        protected readonly FloatField minValueField;
        protected readonly FloatField maxValueField;
        protected readonly UnityEngine.UIElements.MinMaxSlider minMaxSlider;

        internal MinMaxSlider(ElementFactory elementFactory) : base(elementFactory)
        {
            Add(minValueField = EditorElementUtility.elementFactory.CreateFloatField(OnMinValueChangedCallback));
            EditorElementUtility.ApplySubFieldStyle(minValueField);

            Add(minMaxSlider = new UnityEngine.UIElements.MinMaxSlider());
            EditorElementUtility.ApplySubFieldStyle(minMaxSlider);
            minMaxSlider.RegisterValueChangedCallback(OnMinMaxSliderValueChangedCallback);
            minMaxSlider.style.marginLeft = minMaxSlider.style.marginRight = 4f;
            minMaxSlider.style.overflow = Overflow.Visible;
            minMaxSlider.ElementAt(0).style.marginTop = 2f;

            Add(maxValueField = EditorElementUtility.elementFactory.CreateFloatField(OnMaxValueChangedCallback));
            EditorElementUtility.ApplySubFieldStyle(maxValueField);

            minValueField.style.flexGrow = maxValueField.style.flexGrow = 0f;
            minValueField.style.SetWidth(valueFieldWidth);
            minValueField.style.SetMaxWidth(valueFieldWidth);
            maxValueField.style.SetWidth(valueFieldWidth);
            maxValueField.style.SetMaxWidth(valueFieldWidth);
        }

        public override void SetValueWithoutNotify(Vector2 value)
        {
            base.SetValueWithoutNotify(value);
            UpdateDisplayValue(value);
        }

        protected override void SetValue(Vector2 value)
        {
            base.SetValue(value);
            UpdateDisplayValue(value);
        }
        protected override void OnRedo(Vector2 newValue)
        {
            base.OnRedo(newValue);
            UpdateDisplayValue(newValue);
        }
        protected override void OnUndo(Vector2 oldValue)
        {
            base.OnUndo(oldValue);
            UpdateDisplayValue(oldValue);
        }

        private void UpdateDisplayValue(Vector2 displayValue)
        {
            minMaxSlider.SetValueWithoutNotify(displayValue);
            minValueField.SetValueWithoutNotify(displayValue.x);
            maxValueField.SetValueWithoutNotify(displayValue.y);
        }

        private void OnMinValueChangedCallback(float newMinValue)
        {
            Vector2 newValue = new Vector2(newMinValue, value.y);
            base.SetValue(newValue);
            minMaxSlider.SetValueWithoutNotify(newValue);
        }
        private void OnMaxValueChangedCallback(float newMaxValue)
        {
            Vector2 newValue = new Vector2(value.x, newMaxValue);
            base.SetValue(newValue);
            minMaxSlider.SetValueWithoutNotify(newValue);
        }
        private void OnMinMaxSliderValueChangedCallback(ChangeEvent<Vector2> changeEvent)
        {
            Vector2 newValue = changeEvent.newValue;
            newValue.x = (float)Math.Round(newValue.x, 2, MidpointRounding.AwayFromZero);
            newValue.y = (float)Math.Round(newValue.y, 2, MidpointRounding.AwayFromZero);
            base.SetValue(newValue);
            minValueField.SetValueWithoutNotify(newValue.x);
            maxValueField.SetValueWithoutNotify(newValue.y);
        }
    }
}